package com.qingzhou.common.security.config;

import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.solon.dao.SaTokenDaoOfRedissonJackson;
import com.qingzhou.common.core.constants.ServiceConstant;
import com.qingzhou.common.security.config.properties.SecurityProperties;
import com.qingzhou.common.security.impl.AuthProcessorImpl;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.auth.AuthAdapter;
import org.noear.solon.auth.AuthRule;
import org.noear.solon.auth.impl.AuthRuleImpl;
import org.noear.solon.core.handle.Context;
import org.redisson.api.RedissonClient;

import java.util.ArrayList;
import java.util.List;

/**
 * 安全配置
 * @author xm
 */
@Configuration
public class SecurityConfig {

    /**
     * SaTokenDao
     * @param redissonClient
     * @return
     */
    @Bean
    @Condition(onClass = RedissonClient.class)
    public SaTokenDao saTokenDaoInit(RedissonClient redissonClient) {
        return new SaTokenDaoOfRedissonJackson(redissonClient);
    }

    /**
     * 安全配置
     * @param securityProperties
     * @return
     */
    @Bean
    public SecurityProperties securityProperties(@Inject("${qingzhou.security}") SecurityProperties securityProperties) {
        return securityProperties;
    }

    /**
     * 鉴权处理（可以在每个模块定制合适的鉴权处理）
     * @return
     */
    @Bean
    @Condition(onMissingBean = AuthAdapter.class)
    public AuthAdapter authAdapter(SecurityProperties securityProperties) {
        AuthProcessorImpl authProcessor = new AuthProcessorImpl();
        authProcessor.setIpBlackList(securityProperties.getIps());
        return new AuthAdapter()
                // 添加规则
                .addRules(getRules(securityProperties))
                // 设定鉴权处理器
                .processor(authProcessor)
                // 设定默认的验证失败处理
                .failure(Context::render);
    }

    /**
     * 定义规则
     * @return
     */
    private List<AuthRule> getRules(SecurityProperties securityProperties) {
        List<AuthRule> list = new ArrayList<>();

        // 所有请求，校验 IP
        AuthRuleImpl ipRule = new AuthRuleImpl();
        AuthRule verifyIp = ipRule.include("/**").verifyIp();
        list.add(verifyIp);

        // 所有请求，排除白名单及服务间调用的路径，校验字符权限
        AuthRuleImpl permissionsRule = new AuthRuleImpl();
        permissionsRule.include("/**");
        for (String path : securityProperties.getWhites()) {
            permissionsRule.exclude(path);
        }
        permissionsRule.exclude(ServiceConstant.PATH_BASE + "/**");
        AuthRule verifyPermissions = permissionsRule.verifyPermissions();
        list.add(verifyPermissions);

        return list;
    }

}
